<!DOCTYPE html>
<html>
  <head>
    <title>Portal Relay {{.Version}}</title>
    <style>
      html,
      body {
        width: 100%;
        height: 100%;
        overflow: hidden;
        user-select: none;
      }

      html {
        line-height: 1.15;
        -webkit-text-size-adjust: 100%;
      }

      body {
        margin: 0;
        background-color: black;
      }

      a {
        text-decoration: none;
      }

      /* no support for reversing a played animation, therefore we replace it with reversed keyframes */
      @keyframes hyperdrive-go {
        0% {
          filter: brightness(0.5);
        }
        50% {
          filter: brightness(1.5);
        }
        80% {
          filter: brightness(1) blur(0) saturate(0);
        }
        100% {
          filter: brightness(0.8) blur(0.5px) saturate(2) hue-rotate(180deg)
            opacity(0.85);
        }
      }
      @keyframes hyperdrive-stop {
        from {
          filter: brightness(2.5);
        }
        to {
          filter: none;
        }
      }

      #infinite-space {
        position: absolute;
        width: 100%;
        height: 100%;
      }

      .container {
        position: absolute;
        top: 0;
        bottom: 0;
        right: 0;
        left: 0;
        display: flex;
      }

      .content {
        display: flex;
        margin: auto;
        flex-direction: column;
        justify-content: center;
        align-items: center;
        cursor: pointer;
        transition: 0.5s ease-in-out;
      }

      .content:hover {
        transform: scale(1.1);
      }

      .relay {
        font-size: 24px;
        font-family: monospace;
        text-align: center;
        color: #f09c3a;
        margin: 0 auto;
        filter: grayscale(0.25);
      }

      .logo {
        width: 220px;
        height: 150px;
        margin: 0 auto;
        filter: grayscale(0.25);
        background-size: cover;
        background-repeat: no-repeat;
        background-position: center;
        background: url("");
      }
    </style>
  </head>

  <body>
    <canvas id="infinite-space"></canvas>
    <div class="container">
      <div class="content" id="hyperdrive-hover-target">
        <a href="https://github.com/SpatiumPortae/portal" target="_blank">
          <div class="logo"></div>
        </a>
        <a
          href="https://github.com/SpatiumPortae/portal/releases"
          target="_blank"
        >
          <p class="relay">relay server</p>
          <p class="relay">
            <b>{{.Version}}</b>
          </p>
        </a>
      </div>
    </div>
  </body>

  <script>
    const DEFAULT_SPEED = 0.03;
    const HYPERDRIVE_SPEED = 0.5;
    const MAX_Z_WARP = 12;

    const hyperDriveTriggerElement = document.getElementById(
      "hyperdrive-hover-target"
    );

    const canvas = document.getElementById("infinite-space");
    canvas.width = document.documentElement.clientWidth;
    canvas.height = document.documentElement.clientHeight;

    const ctx = canvas.getContext("2d");
    ctx.fillStyle = "black";
    ctx.fillRect(0, 0, canvas.width, canvas.height);

    let halfw = canvas.width / 2,
      halfh = canvas.height / 2,
      speed = DEFAULT_SPEED;

    const randRange = (from, to) => from + Math.floor(Math.random() * to * 2);
    const generateColor = () => `hsla(45, 100%, ${randRange(85, 100)}%, 1)`;

    function Star() {
      this.posVec = [
        randRange(-halfw, halfw),
        randRange(-halfh, halfh),
        randRange(1, MAX_Z_WARP),
      ];
      this.x = this.posVec[0];
      this.y = this.posVec[1];
      this.z = this.posVec[2];
      this.color = generateColor();
      this.vel = [0, 0, -speed];

      this.reset = function () {
        this.posVec = [
          randRange(-halfw, halfw),
          randRange(-halfh, halfh),
          randRange(1, MAX_Z_WARP),
        ];
        this.x = this.posVec[0];
        this.y = this.posVec[1];
        this.color = generateColor();
        this.vel = [0, 0, -speed];
      };

      this.draw = function () {
        this.posVec = [
          this.posVec[0] + this.vel[0],
          this.posVec[1] + this.vel[1],
          this.posVec[2] + this.vel[2],
        ];
        const x = this.posVec[0] / this.posVec[2];
        const y = this.posVec[1] / this.posVec[2];
        const x2 = this.posVec[0] / (this.posVec[2] + speed);
        const y2 = this.posVec[1] / (this.posVec[2] + speed);

        ctx.strokeStyle = this.color;
        ctx.beginPath();
        ctx.moveTo(x, y);
        ctx.lineTo(x2, y2);
        ctx.stroke();

        if (x < -halfw || x > halfw || y < -halfh || y > halfh) this.reset();
      };
    }

    function StarField() {
      this.starCount = 300;
      this.isInHyperDrive = false;
      this.stars = Array.from({ length: this.starCount }, () => new Star());

      this.startHyperDrive = function () {
        this.isInHyperDrive = true;
        canvas.style.animation = "hyperdrive-go 6s ease-in normal forwards";
      };

      this.stopHyperDrive = function () {
        this.isInHyperDrive = false;
        ctx.translate(-halfw, -halfh);
        ctx.fillStyle = "rgba(0, 0, 0, 1.0)";
        ctx.fillRect(0, 0, canvas.width, canvas.height);
        canvas.style.animation = "hyperdrive-stop 1s ease-out normal forwards";
      };

      this.draw = function () {
        speed = this.isInHyperDrive
          ? Math.min(speed * 1.075, HYPERDRIVE_SPEED)
          : Math.max(speed * 0.85, DEFAULT_SPEED);

        ctx.translate(halfw, halfh);
        this.stars.forEach((star) => star.draw());
      };
    }

    const starField = new StarField();
    const render = () => {
      ctx.setTransform(1, 0, 0, 1, 0, 0);
      ctx.fillStyle = "rgba(0, 0, 0, 0.5)";
      ctx.fillRect(0, 0, canvas.width, canvas.height);
      starField.draw();
      window.requestAnimationFrame(render);
    };

    hyperDriveTriggerElement.addEventListener("mouseenter", () =>
      starField.startHyperDrive()
    );
    hyperDriveTriggerElement.addEventListener("mouseleave", () =>
      starField.stopHyperDrive()
    );

    window.addEventListener("load", render);
    window.addEventListener("resize", () => {
      canvas.width = document.documentElement.clientWidth;
      canvas.height = document.documentElement.clientHeight;
      halfw = canvas.width / 2;
      halfh = canvas.height / 2;
    });
  </script>
</html>
